package com.rkc.controller;


import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.alipay.api.response.AlipayTradeWapPayResponse;
import com.rkc.config.AlipayConfiguration;
import com.rkc.config.PayUrlConfiguration;
import com.rkc.constant.CacheKey;
import com.rkc.enums.BizCodeEnum;
import com.rkc.enums.ClientType;
import com.rkc.enums.ProductOrderPayTypeEnum;
import com.rkc.interceptor.LoginInterceptor;
import com.rkc.model.LoginUser;
import com.rkc.request.ConfirmOrderRequest;
import com.rkc.request.RepayOrderRequest;
import com.rkc.service.ProductOrderService;
import com.rkc.utils.CommonUtil;
import com.rkc.utils.JsonData;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author 冉堃赤
 * @since 2021-10-30
 */
@Slf4j
@Api("订单模块")
@RestController
@RequestMapping("/api/order/v1")
public class ProductOrderController {

    @Autowired
    private ProductOrderService productOrderService;

    @Autowired
    private PayUrlConfiguration payUrlConfiguration;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 前端在进入结算页面，confirm提交订单之前，获取提交表单的令牌，主要用于防止重复点击下单
     * @return
     */
    @ApiOperation("获取提交表单令牌")
    @GetMapping("get_token")
    public JsonData getOrderToken() {
        LoginUser loginUser = LoginInterceptor.THREAD_LOCAL.get();
        String key = String.format(CacheKey.SUBMIT_ORDER_TOKEN_KEY, loginUser.getId()), token = CommonUtil.getStringNumRandom(32);
        //30分钟过期时间
        stringRedisTemplate.opsForValue().set(key, token, 30, TimeUnit.MINUTES);
        return JsonData.buildSuccess(token);
    }

    /**
     * 查询订单状态
     * 没有登录拦截，可以增加秘钥进行RPC通信
     * @param outTradeNo
     * @return
     */
    @ApiOperation("查询订单状态")
    @GetMapping("query_state")
    public JsonData queryProductOrderState(@RequestParam("out_trade_no") String outTradeNo) {
        String state = productOrderService.queryProductOrderState(outTradeNo);
        return StringUtils.isBlank(state) ? JsonData.buildResult(BizCodeEnum.ORDER_CONFIRM_NOT_EXIST) : JsonData.buildSuccess(state);
    }

    @ApiOperation("提交订单")
    @PostMapping("confirm")
    public void confirmOrder(@ApiParam("订单提交对象") @RequestBody ConfirmOrderRequest confirmOrderRequest, HttpServletResponse response) {
        JsonData result = productOrderService.confirmOrder(confirmOrderRequest);
        if (result.getCode() == 0) {
            String client = confirmOrderRequest.getClientType(), payType = confirmOrderRequest.getPayType();
            //如果是支付宝网页支付，都是跳转网页，app除外
            if (ProductOrderPayTypeEnum.ALIPAY.name().equalsIgnoreCase(payType)) {
                log.info("创建支付宝订单成功：{}", confirmOrderRequest);
                if (ClientType.H5.name().equalsIgnoreCase(client)) {
                    //网页支付
                    writeResponseStream(response, result);
                } else if (ClientType.APP.name().equalsIgnoreCase(client)) {
                    //TODO app sdk支付
                }
            } else if (ProductOrderPayTypeEnum.WECHAT.name().equalsIgnoreCase(payType)) {
                //TODO 微信支付
            }
        } else {
            log.error("创建订单失败：{}", response.toString());
            CommonUtil.sendJsonMessage(response, result);
        }
    }

    @ApiOperation("重新支付订单")
    @PostMapping("repay")
    public void repay(@ApiParam("订单对象") @RequestBody RepayOrderRequest repayOrderRequest, HttpServletResponse response) {
        JsonData result = productOrderService.repay(repayOrderRequest);
        if (result.getCode() == 0) {
            String client = repayOrderRequest.getClientType(), payType = repayOrderRequest.getPayType();
            //如果是支付宝网页支付，都是跳转网页，app除外
            if (ProductOrderPayTypeEnum.ALIPAY.name().equalsIgnoreCase(payType)) {
                log.info("重新支付订单成功：{}", repayOrderRequest);
                if (ClientType.H5.name().equalsIgnoreCase(client)) {
                    //网页支付
                    writeResponseStream(response, result);
                } else if (ClientType.APP.name().equalsIgnoreCase(client)) {
                    //TODO app sdk支付
                }
            } else if (ProductOrderPayTypeEnum.WECHAT.name().equalsIgnoreCase(payType)) {
                //TODO 微信支付
            }
        } else {
            log.error("重新支付订单失败：{}", response.toString());
            CommonUtil.sendJsonMessage(response, result);
        }
    }

    /**
     * JsonData的数据写到网页中
     * @param response
     * @param jsonData
     */
    private void writeResponseStream(HttpServletResponse response, JsonData jsonData) {
        try {
            response.setContentType("text/html;charset=utf8");
            PrintWriter writer = response.getWriter();
            writer.write(jsonData.getData().toString());
            writer.flush();
            writer.close();
        } catch (IOException e) {
            log.error("html写出异常：{}", e.toString());
        }
    }

    /**
     * 测试支付方法
     * @param response
     */
    @GetMapping("test_pay")
    public void testAlipay(HttpServletResponse response) throws AlipayApiException, IOException {
        Map<String, String> content = new HashMap<>(10);
        //商户订单号,64个字符以内、可包含字母、数字、下划线；需保证在商户端不重复
        String no = UUID.randomUUID().toString();
        log.info("订单号:{}", no);
        content.put("out_trade_no", no);
        content.put("product_code", "FAST_INSTANT_TRADE_PAY");
        //订单总金额，单位为元，精确到小数点后两位
        content.put("total_amount", "111.99");
        //商品标题/交易标题/订单标题/订单关键字等。 注意：不可使用特殊字符，如 /，=，&amp; 等。
        content.put("subject", "杯子");
        //商品描述，可空
        content.put("body", "好的杯子");
        // 该笔订单允许的最晚付款时间，逾期将关闭交易。取值范围：1m～15d。m-分钟，h-小时，d-天，1c-当天（1c-当天的情况下，无论交易何时创建，都在0点关闭）。 该参数数值不接受小数点， 如 1.5h，可转换为 90m。
        content.put("timeout_express", "5m");
        AlipayTradeWapPayRequest payRequest = new AlipayTradeWapPayRequest();
        payRequest.setBizContent(JSON.toJSONString(content));
        payRequest.setNotifyUrl(payUrlConfiguration.getAlipayCallbackUrl());
        payRequest.setReturnUrl(payUrlConfiguration.getAlipaySuccessReturnUrl());
        //得到执行后的响应
        AlipayTradeWapPayResponse payResponse = AlipayConfiguration.getInstance().pageExecute(payRequest);
        if (payResponse.isSuccess()) {
            System.out.println("调用成功");
            String body = payResponse.getBody();
            response.setContentType("text/html;charset=UTF-8");
            response.getWriter().write(body);
            response.getWriter().flush();
            response.getWriter().close();
        } else {
            System.out.println("调用失败");
        }
    }
}

